<template>
  <div class="data-source-container">
    <div class="header">
      <h2>数据源接入</h2>
    </div>

    <el-row :gutter="20">
      <!-- 左侧：数据源配置 -->
      <el-col :span="12">
        <el-card>
          <template #header>
            <div class="card-header">
              <span>数据源配置</span>
            </div>
          </template>

          <el-tabs v-model="activeTab" type="card">
            <!-- API数据源 -->
            <el-tab-pane label="API数据源" name="api">
              <div class="api-config">
                <el-form :model="apiConfig" label-width="100px">
                  <el-form-item label="数据源类型">
                    <el-select v-model="apiConfig.dataSourceType" placeholder="选择数据源">
                      <el-option label="天天基金(东方财富)" value="TIANJIN"></el-option>
                    </el-select>
                  </el-form-item>

                </el-form>
              </div>
            </el-tab-pane>

            <!-- 文件上传 -->
            <el-tab-pane label="文件上传" name="file">
              <div class="file-upload">
                <el-upload
                  class="upload-demo"
                  drag
                  :action="uploadUrl"
                  :headers="uploadHeaders"
                  :data="uploadData"
                  :before-upload="beforeUpload"
                  :on-success="onUploadSuccess"
                  :on-error="onUploadError"
                  :on-change="onFileChange"
                  :file-list="fileList"
                  :auto-upload="true"
                  accept=".csv,.xlsx,.xls"
                >
                  <el-icon class="el-icon--upload"><upload-filled /></el-icon>
                  <div class="el-upload__text">将文件拖到此处，或<em>点击上传</em></div>
                  <template #tip>
                    <div class="el-upload__tip">
                      支持 CSV、Excel 文件，文件大小不超过 10MB
                    </div>
                  </template>
                </el-upload>

                <!-- 文件预览信息 -->
                <div v-if="filePreviewInfo" class="file-preview-info">
                  <el-alert
                    :title="`文件解析成功：共 ${filePreviewInfo.totalRows} 行数据，预览前 ${filePreviewInfo.previewRows} 行`"
                    type="success"
                    :closable="false"
                    show-icon
                  />
                  <div class="preview-actions">
                    <el-button type="primary" @click="saveFileData" :loading="saving">
                      保存因子数据到数据库
                    </el-button>
                    <el-button type="primary" @click="saveNavData" :loading="saving">
                      保存原始数据到数据库
                    </el-button>
                    <el-button @click="clearFilePreview">清除预览</el-button>
                    <el-button v-if="!hasValidFile" type="warning" @click="showReuploadTip">
                      重新上传文件
                    </el-button>
                  </div>
                </div>

                <div class="column-mapping" v-if="showColumnMapping">
                  <h4>列映射配置</h4>
                  <el-form :model="columnMapping" label-width="100px">
                    <el-form-item
                      v-for="(column, index) in fileColumns"
                      :key="index"
                      :label="column"
                    >
                      <el-select v-model="columnMapping[column]" placeholder="选择映射字段">
                        <el-option
                          v-for="factor in availableFactors"
                          :key="factor.code"
                          :label="factor.name"
                          :value="factor.code"
                        ></el-option>
                      </el-select>
                    </el-form-item>
                    <el-form-item>
                      <el-button type="primary" @click="processFileMapping">确认映射</el-button>
                    </el-form-item>
                  </el-form>
                </div>
              </div>
            </el-tab-pane>

            <!-- Python脚本 -->
            <el-tab-pane label="Python脚本" name="python">
              <div class="python-script">
                <!-- 新增：说明和示例代码 -->
                <el-alert
                  title="示例：请粘贴如下Python代码，字段需与factors表一致，输出为JSON数组。"
                  type="info"
                  :closable="false"
                  show-icon
                  style="margin-bottom: 10px;"
                />
                <el-card class="example-python-card" style="margin-bottom: 20px;">
                  <pre style="white-space: pre-wrap; font-size: 13px; background: #f8f8f8; padding: 10px; border-radius: 4px;">
import pandas as pd

# 构造因子数据，字段需与factors表一致
data = [
    {
        "factorCode": "FACTOR001",
        "factorName": "夏普比率因子",
        "factorType": "收益类",
        "fundCode": "FUND123",
        "value": 1.23,
        "description": "示例因子1"
    },
    {
        "factorCode": "FACTOR002",
        "factorName": "波动率因子",
        "factorType": "风险类",
        "fundCode": "FUND456",
        "value": 2.34,
        "description": "示例因子2"
    }
]

df = pd.DataFrame(data)
# 输出为JSON数组，后端会自动识别
print(df.to_json(orient="records", force_ascii=False))
                  </pre>
                </el-card>
                <!-- 新增：自定义Python代码输入框和执行按钮 -->
                <el-card class="custom-python-card" style="margin-bottom: 20px;">
                  <template #header>
                    <div class="card-header">
                      <span>自定义Python代码接入</span>
                    </div>
                  </template>
                  <el-form label-width="80px">
                    <el-form-item label="Python">
                      <el-input
                        v-model="pythonConfig.script"
                        type="textarea"
                        :rows="12"
                        placeholder="请粘贴你的Python代码，要求print输出DataFrame.to_json(orient='records')"
                      />
                    </el-form-item>
                    <el-form-item>
                      <el-button type="primary" :loading="executing" @click="executeCustomPythonCode">执行并接入</el-button>
                    </el-form-item>
                  </el-form>
                </el-card>
              </div>
            </el-tab-pane>

            <!-- 自定义API -->

          </el-tabs>
        </el-card>
      </el-col>

      <!-- 右侧：数据预览 -->
      <el-col :span="12">
        <el-card>
          <template #header>
            <div class="card-header">
              <span>数据预览</span>
              <div class="preview-actions">
                <el-button size="small" @click="refreshPreview">刷新</el-button>
                <el-button size="small" @click="exportPreviewData" v-if="previewData.length > 0">导出</el-button>
              </div>
            </div>
          </template>

          <div class="data-preview">
            <div v-if="previewData.length > 0">
              <!-- 预览信息 -->
              <div class="preview-stats">
                <el-tag type="info">总记录数: {{ previewData.length }}</el-tag>
                <el-tag type="success">更新时间: {{ lastUpdateTime }}</el-tag>
                <el-tag v-if="filePreviewInfo" type="warning">预览模式: 显示前 {{ filePreviewInfo.previewRows }} 行</el-tag>
              </div>

              <!-- 数据表格 -->
              <el-table :data="previewData" height="350" style="width: 100%" border>
                <el-table-column
                  v-for="column in previewColumns"
                  :key="column"
                  :prop="column"
                  :label="column"
                  width="120"
                  show-overflow-tooltip
                >
                  <template #default="scope">
                    <span v-if="typeof scope.row[column] === 'number'">
                      {{ formatNumber(scope.row[column]) }}
                    </span>
                    <span v-else>
                      {{ scope.row[column] }}
                    </span>
                  </template>
                </el-table-column>
              </el-table>
            </div>
            <div v-else class="empty-preview">
              <el-empty description="暂无数据，请先获取或上传数据"></el-empty>
            </div>
          </div>
        </el-card>
      </el-col>
    </el-row>


  </div>
</template>

<script>
import { ref, reactive, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { UploadFilled } from '@element-plus/icons-vue'
import axios from "axios";

export default {
  name: 'DataSource',
  components: {
    UploadFilled
  },
  setup() {
    // 响应式数据
    const activeTab = ref('api')
    const fetching = ref(false)
    const updating = ref(false)
    const executing = ref(false)
    const calling = ref(false)
    const saving = ref(false)
    const showColumnMapping = ref(false)
    const fileList = ref([])
    const previewData = ref([])
    const previewColumns = ref([])
    const lastUpdateTime = ref('')
    const filePreviewInfo = ref(null)
    const hasValidFile = ref(false)

    const apiConfig = reactive({
      dataSourceType: 'TIANJIN',
      fundCode: ''
    })

    const pythonConfig = reactive({
      script: '',
      parameters: '{}'
    })

    const customApiConfig = reactive({
      apiUrl: '',
      method: 'GET',
      headers: '{}',
      params: '{}',
      responseMapping: '{}'
    })

    const columnMapping = reactive({})
    const fileColumns = ref([])

    const availableFunds = ref([])
    const availableFactors = ref([])
    const dataStatus = reactive({
      cacheSize: 0,
      supportedFunds: 0,
      supportedFactors: 0,
      lastUpdate: null
    })

    const uploadUrl = 'http://localhost:8080/data/file/upLoad'
    const uploadHeaders = {}
    const uploadData = {}

    // Python脚本管理相关数据和方法
    const scripts = ref([])
    const selectedScript = ref(null)
    const envInfo = reactive({})
    const envChecked = ref(false)
    const checking = ref(false)
    const validating = ref(false)
    const uploading = ref(false)
    const creating = ref(false)
    const showUploadDialog = ref(false)
    const showCreateDialog = ref(false)
    const showExecutionParams = ref(false)
    const executionResult = ref(null)
    const executionParams = ref('')
    const selectedTemplate = ref('')
    const newScript = reactive({ name: '', content: '' })
    const uploadFileRef = ref(null)

    // 方法
    const loadDataStatus = async () => {
    }

    const loadAvailableData = async () => {
    }

    const fetchApiData = async () => {

    }

    const updateApiData = async () => {
    }

    const beforeUpload = (file) => {
      const isValidType =
          file.type === 'text/csv' ||
          file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' ||
          file.type === 'application/vnd.ms-excel';

      const isLt10M = file.size / 1024 / 1024 < 10

      if (!isValidType) {
        ElMessage.error('只能上传CSV或Excel文件!')
        return false
      }
      if (!isLt10M) {
        ElMessage.error('文件大小不能超过10MB!')
        return false
      }
      return true
    }

    const onUploadSuccess = (response, file) => {
      if (response.success) {
        ElMessage.success('文件上传成功')
        previewData.value = response.data.data || []
        previewColumns.value = response.data.columns || []
        fileColumns.value = response.data.columns || []
        filePreviewInfo.value = {
          totalRows: response.data.totalRows,
          previewRows: response.data.previewRows,
          processedAt: response.data.processedAt
        }
        lastUpdateTime.value = new Date().toLocaleString()
        
        // 确保文件对象正确保存
        if (fileList.value.length === 0) {
          fileList.value = [file]
        } else {
          // 如果已有文件，替换为当前文件
          fileList.value = [file]
        }
        
        // 检查文件对象是否有效
        const currentFile = fileList.value[0]
        hasValidFile.value = !!(currentFile && (currentFile.raw || currentFile.originFileObj || currentFile instanceof File))
        
        console.log('File uploaded successfully:', currentFile)
        console.log('Has valid file:', hasValidFile.value)
      } else {
        ElMessage.error(response.message || '文件上传失败')
      }
    }

    const onUploadError = (error) => {
      console.error('Upload error:', error)
      ElMessage.error('文件上传失败，请检查文件格式或网络连接')
    }

    const onFileChange = (file, fileList) => {
      // 处理文件选择事件，确保文件对象正确保存
      console.log('File changed:', file)
      console.log('File list:', fileList)
      
      // 更新文件列表，确保包含原始文件对象
      if (fileList && fileList.length > 0) {
        // 确保文件对象包含raw属性
        const currentFile = fileList[fileList.length - 1]
        if (currentFile && !currentFile.raw && currentFile.originFileObj) {
          currentFile.raw = currentFile.originFileObj
        }
      }
    }

    const saveNavData = async () => {
      console.log('Current fileList:', fileList.value)
      
      if (!fileList.value.length) {
        ElMessage.warning('请先上传文件')
        return
      }

      saving.value = true
      try {
        const formData = new FormData()
        const file = fileList.value[0]
        
        console.log('File object:', file)
        console.log('File.raw:', file.raw)
        console.log('File.originFileObj:', file.originFileObj)
        
        // 尝试多种方式获取文件对象
        let fileToUpload = null
        
        if (file.raw) {
          fileToUpload = file.raw
        } else if (file.originFileObj) {
          fileToUpload = file.originFileObj
        } else if (file instanceof File) {
          fileToUpload = file
        } else {
          // 如果都没有，尝试从文件URL重新获取
          ElMessage.warning('文件对象不完整，请重新上传文件')
          return
        }
        
        console.log('File to upload:', fileToUpload)
        formData.append('file', fileToUpload)

        const response = await axios.post('http://localhost:8080/data/Nav/save', formData, {
          headers: {
            'Content-Type': 'multipart/form-data'
          }
        })

        console.log('Save response:', response)

        if (response.data.success) {
          ElMessage.success(response.data.message)
          clearFilePreview()
        } else {
          ElMessage.error(response.data.message || '数据保存失败')
        }
      } catch (error) {
        console.error('Save file error:', error)
        ElMessage.error('数据保存失败: ' + (error.response?.data?.message || error.message))
      } finally {
        saving.value = false
      }
    }
    const saveFileData = async () => {
      console.log('Current fileList:', fileList.value)

      if (!fileList.value.length) {
        ElMessage.warning('请先上传文件')
        return
      }

      saving.value = true
      try {
        const formData = new FormData()
        const file = fileList.value[0]

        console.log('File object:', file)
        console.log('File.raw:', file.raw)
        console.log('File.originFileObj:', file.originFileObj)

        // 尝试多种方式获取文件对象
        let fileToUpload = null

        if (file.raw) {
          fileToUpload = file.raw
        } else if (file.originFileObj) {
          fileToUpload = file.originFileObj
        } else if (file instanceof File) {
          fileToUpload = file
        } else {
          // 如果都没有，尝试从文件URL重新获取
          ElMessage.warning('文件对象不完整，请重新上传文件')
          return
        }

        console.log('File to upload:', fileToUpload)
        formData.append('file', fileToUpload)

        const response = await axios.post('http://localhost:8080/data/file/save', formData, {
          headers: {
            'Content-Type': 'multipart/form-data'
          }
        })

        console.log('Save response:', response)

        if (response.data.success) {
          ElMessage.success(response.data.message)
          clearFilePreview()
        } else {
          ElMessage.error(response.data.message || '数据保存失败')
        }
      } catch (error) {
        console.error('Save file error:', error)
        ElMessage.error('数据保存失败: ' + (error.response?.data?.message || error.message))
      } finally {
        saving.value = false
      }
    }


    const clearFilePreview = () => {
      previewData.value = []
      previewColumns.value = []
      fileColumns.value = []
      filePreviewInfo.value = null
      fileList.value = []
      showColumnMapping.value = false
      hasValidFile.value = false
    }
    const saveScript = async () => {
      // 保存脚本到本地存储
      localStorage.setItem('pythonScript', pythonConfig.script)
      localStorage.setItem('pythonParameters', pythonConfig.parameters)
      ElMessage.success('脚本已保存')
    }

    const callCustomAPI = async () => {
    }

    const testApi = async () => {
    }

    const refreshData = () => {
      loadDataStatus()
      loadAvailableData()
    }

    const batchUpdate = async () => {
    }

    const refreshPreview = () => {
      // 刷新数据预览
      if (previewData.value.length > 0) {
        lastUpdateTime.value = new Date().toLocaleString()
      }
    }

    const exportPreviewData = () => {
      if (previewData.value.length === 0) {
        ElMessage.warning('没有数据可导出')
        return
      }

      // 创建CSV内容
      const headers = previewColumns.value.join(',')
      const rows = previewData.value.map(row => 
        previewColumns.value.map(col => {
          const value = row[col]
          return typeof value === 'string' && value.includes(',') ? `"${value}"` : value
        }).join(',')
      )
      const csvContent = [headers, ...rows].join('\n')

      // 下载文件
      const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' })
      const link = document.createElement('a')
      const url = URL.createObjectURL(blob)
      link.setAttribute('href', url)
      link.setAttribute('download', `data_preview_${new Date().toISOString().slice(0, 10)}.csv`)
      link.style.visibility = 'hidden'
      document.body.appendChild(link)
      link.click()
      document.body.removeChild(link)
    }

    const formatNumber = (value) => {
      if (typeof value === 'number') {
        return value.toFixed(4)
      }
      return value
    }

    const formatDate = (date) => {
      if (!date) return '未知'
      return new Date(date).toLocaleString()
    }

    const showReuploadTip = () => {
      ElMessage.warning('请重新上传文件以确保文件对象完整')
      clearFilePreview()
    }

    const checkEnvironment = async () => {
      // 实现环境检查逻辑
    }

    const loadScripts = async () => {
      // 实现加载脚本列表的逻辑
    }

    const selectScript = (script) => {
      // 实现选择脚本的逻辑
    }

    const validateScript = async () => {
      // 实现脚本验证逻辑
    }

    const executeScript = async () => {
      // 实现脚本执行逻辑
    }

    const deleteScript = async (scriptId) => {
      // 实现删除脚本的逻辑
    }

    const createScript = async () => {
      // 实现创建新脚本的逻辑
    }

    const handleFileChange = (file) => {
      // 实现文件上传前的处理逻辑
    }

    const uploadFile = async () => {
      // 实现文件上传的逻辑
    }

    const loadTemplate = async () => {
      // 实现加载脚本模板的逻辑
    }

    const onCodeChange = () => {
      // 实现代码编辑时的处理逻辑
    }

    const formatFileSize = (bytes) => {
      // 实现格式化文件大小的逻辑
    }

    const formatTime = (timeStr) => {
      // 实现格式化时间的逻辑
    }

    const executeCustomPythonCode = async () => {
      if (!pythonConfig.script) {
        ElMessage.warning('请输入Python代码')
        return
      }
      executing.value = true
      try {
        const response = await axios.post('http://localhost:8080/data/api/python/execute-code', {
          code: pythonConfig.script
        })
        if (response.data.success) {
          ElMessage.success('接入成功！')
          // 可选：刷新因子数据预览
          refreshPreview()
        } else {
          ElMessage.error('接入失败：' + (response.data.message || '返回值结构不符合factors表'))
        }
      } catch (error) {
        ElMessage.error('执行失败：' + (error.response?.data?.message || error.message))
      } finally {
        executing.value = false
      }
    }

    // 生命周期
    onMounted(() => {
      loadDataStatus()
      loadAvailableData()

      // 加载保存的Python脚本
      const savedScript = localStorage.getItem('pythonScript')
      const savedParameters = localStorage.getItem('pythonParameters')
      if (savedScript) {
        pythonConfig.script = savedScript
      }
      if (savedParameters) {
        pythonConfig.parameters = savedParameters
      }

      checkEnvironment()
    })

    return {
      activeTab,
      fetching,
      updating,
      executing,
      calling,
      saving,
      showColumnMapping,
      fileList,
      previewData,
      previewColumns,
      lastUpdateTime,
      filePreviewInfo,
      hasValidFile,
      apiConfig,
      pythonConfig,
      customApiConfig,
      columnMapping,
      fileColumns,
      availableFunds,
      availableFactors,
      dataStatus,
      uploadUrl,
      uploadHeaders,
      uploadData,

      fetchApiData,
      updateApiData,
      beforeUpload,
      onUploadSuccess,
      onUploadError,
      onFileChange,
      saveFileData,
      saveNavData,
      clearFilePreview,
      saveScript,
      callCustomAPI,
      testApi,
      refreshData,
      batchUpdate,
      refreshPreview,
      exportPreviewData,
      formatNumber,
      formatDate,
      showReuploadTip,

      scripts,
      selectedScript,
      envInfo,
      envChecked,
      checking,
      validating,
      uploading,
      creating,
      showUploadDialog,
      showCreateDialog,
      showExecutionParams,
      executionResult,
      executionParams,
      selectedTemplate,
      newScript,
      uploadFileRef,

      checkEnvironment,
      loadScripts,
      selectScript,
      validateScript,
      executeScript,
      deleteScript,
      createScript,
      handleFileChange,
      uploadFile,
      loadTemplate,
      onCodeChange,
      formatFileSize,
      formatTime,
      executeCustomPythonCode
    }
  }
}
</script>

<style scoped>
.data-source-container {
  padding: 20px;
}

.header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
}

.header h2 {
  margin: 0;
  color: #333;
}

.header-actions {
  display: flex;
  gap: 10px;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.preview-actions {
  display: flex;
  gap: 10px;
}

.api-config,
.file-upload,
.python-script,
.custom-api {
  padding: 10px 0;
}

.file-preview-info {
  margin-top: 20px;
  padding: 15px;
  background: #f0f9ff;
  border-radius: 4px;
  border: 1px solid #b3d8ff;
}

.preview-actions {
  margin-top: 10px;
  display: flex;
  gap: 10px;
}

.column-mapping {
  margin-top: 20px;
  padding: 15px;
  background: #f9f9f9;
  border-radius: 4px;
}

.column-mapping h4 {
  margin: 0 0 15px 0;
  color: #333;
}

.data-preview {
  min-height: 400px;
}

.preview-stats {
  margin-bottom: 15px;
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}

.empty-preview {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 400px;
}

.preview-info {
  margin-top: 10px;
  padding: 10px;
  background: #f5f5f5;
  border-radius: 4px;
}

.preview-info p {
  margin: 5px 0;
  font-size: 12px;
  color: #666;
}

.status-item {
  text-align: center;
  padding: 20px;
  background: #f9f9f9;
  border-radius: 4px;
}

.status-title {
  font-size: 14px;
  color: #666;
  margin-bottom: 10px;
}

.status-value {
  font-size: 24px;
  font-weight: bold;
  color: #409EFF;
}

.upload-demo {
  width: 100%;
}

.el-upload__tip {
  color: #909399;
  font-size: 12px;
  margin-top: 10px;
}

.el-upload__text {
  margin: 10px 0;
}

.el-upload__text em {
  color: #409EFF;
  font-style: normal;
}

.env-card {
  margin-bottom: 20px;
}

.env-info {
  padding: 10px;
}

.env-item {
  margin-bottom: 10px;
}

.env-item strong {
  font-weight: bold;
}

.package-list {
  margin-top: 10px;
}

.script-list-card {
  margin-bottom: 20px;
}

.script-list {
  max-height: 300px;
  overflow-y: auto;
}

.script-item {
  padding: 10px;
  cursor: pointer;
  transition: background-color 0.3s;
}

.script-item:hover {
  background-color: #f0f0f0;
}

.script-item.active {
  background-color: #e6f7ff;
}

.script-name {
  font-size: 14px;
  font-weight: bold;
  margin-bottom: 5px;
}

.script-info {
  font-size: 12px;
  color: #666;
}

.script-actions {
  margin-top: 5px;
  text-align: right;
}

.script-editor-card {
  margin-bottom: 20px;
}

.script-editor {
  padding: 10px;
}

.editor-toolbar {
  margin-bottom: 10px;
}

.code-editor {
  margin-bottom: 10px;
}

.execution-params {
  margin-bottom: 10px;
}

.execution-params h4 {
  margin-bottom: 5px;
}

.execution-result-card {
  margin-bottom: 20px;
}

.result-content {
  padding: 10px;
}

.result-details {
  margin-top: 10px;
}

.output-text {
  white-space: pre-wrap;
}

.data-text {
  white-space: pre-wrap;
}

.custom-python-card {
  margin-bottom: 20px;
}

.example-python-card {
  margin-bottom: 20px;
}
</style>
